subroutine manual(what)
  character*(*) what
  write(*,*)
  if (what.eq.'all') then
     write(*,'("	     ______________________________________________")')
     write(*,'("")')
     write(*,'("			   OPTOOL USER GUIDE")')
     write(*,'("")')
     write(*,'("	      Carsten Dominik, Michiel Min, and Ryo Tazaki")')
     write(*,'("	     ______________________________________________")')
     write(*,'("")')
     write(*,'("			June 2021, version 1.9.4")')
     write(*,'("")')
     write(*,'("1 Introduction")')
     write(*,'("==============")')
     write(*,'("")')
     write(*,'("  This tool produces complex dust particle opacities right from the")')
     write(*,'("  command line. It is derived from Michiel Min s DHS [OpacityTool] and")')
     write(*,'("  also implements Ryo Tazaki s MMF theory for highly porous aggregates.")')
     write(*,'("")')
     write(*,'("1.1 Capabilities")')
     write(*,'("~~~~~~~~~~~~~~~~")')
     write(*,'("")')
     write(*,'("  - stand-alone tool, fully command line driven, no input files need to")')
     write(*,'("    be edited")')
     write(*,'("  - full scattering matrix output in several formats, including for")')
     write(*,'("    RADMC-3D")')
     write(*,'("  - combining materials through mixing into a complex grain with")')
     write(*,'("    porosity")')
     write(*,'("  - /built-in/: a curated collection of materials for applications in")')
     write(*,'("    astronomy")')
     write(*,'("  - external refractive index data can be used just as easily")')
     write(*,'("  - computational methods: (i) *DHS (Distribution of Hollow Spheres)*")')
     write(*,'("    for /irregular grains/ and /low-porosity/ aggregates.  Standard *Mie")')
     write(*,'("    theory* for /perfect spheres/ is available as a limiting case. (ii)")')
     write(*,'("    *MMF (Modified Mean Field)* theory for /high-porosity/fractal")')
     write(*,'("    aggregates/. (iii) *CDE* approximation in the Rayleigh limit.")')
     write(*,'("  -  Python  interface module for plotting and post-processing")')
     write(*,'("")')
     write(*,'("1.2 Terms of use")')
     write(*,'("~~~~~~~~~~~~~~~~")')
     write(*,'("")')
     write(*,'("   optool  is distributed under the [MIT license] and can be used,")')
     write(*,'("  changed and redistributed freely. But we do ask you to provide a")')
     write(*,'("  reference to  optool  when using it.  Relevant references are listed")')
     write(*,'("  below and the corresponding BibTeX entries are available in the file")')
     write(*,'("   optool.bib .  optool  is [hosted on github].")')
     write(*,'("")')
     write(*,'("  - *optool:* [Dominik, C., Min, M. & Tazaki, R. 2021, Optool, 1.9,")')
     write(*,'("    Astrophysics Source Code Library, ascl:2104.010]")')
     write(*,'("  - *DHS model for irregular grains:* [Min, M. et al. 2005, A&A, 432,")')
     write(*,'("     909]")')
     write(*,'("  - *MMF model for aggregates:* [Tazaki, R. & Tanaka,H. 2018, ApJ 860,")')
     write(*,'("     79]")')
     write(*,'("  - *DIANA standard Opacities:* [Woitke, P. et al. 2016, A&A 586, 103]")')
     write(*,'("  - *Third party software:* [Toon, O. et al. 1981, Applied Optics 20,")')
     write(*,'("     3657]")')
     write(*,'("  - References to [refractive index data] used in your particular")')
     write(*,'("    application.")')
     write(*,'("")')
     write(*,'("2 Examples")')
     write(*,'("==========")')
     write(*,'("")')
     write(*,'("  A simple grain made only of the default pyroxene, for the default")')
     write(*,'("  grain size distribution ($a^{-3.5}$ powerlaw from 0.05 to 3000mum), on")')
     write(*,'("  the default wavelength grid (0.05mum to 1cm).")')
     write(*,'("")')
     write(*,'("  ,----")')
     write(*,'("  | optool pyr")')
     write(*,'("   ----")')
     write(*,'("")')
     write(*,'("  Include the scattering matrix in the produced output")')
     write(*,'("")')
     write(*,'("  ,----")')
     write(*,'("  | optool pyr -s")')
     write(*,'("   ----")')
     write(*,'("")')
     write(*,'("  Reproduce the DIANA standard dust model, using a specific pyroxene")')
     write(*,'("  (70% Mg) and carbon, in a mass ratio 0.87/0.13, and with a porosity of")')
     write(*,'("  25%.")')
     write(*,'("")')
     write(*,'("  ,----")')
     write(*,'("  | optool pyr-mg70 0.87  c 0.13  -p 0.25")')
     write(*,'("   ----")')
     write(*,'("")')
     write(*,'("  List the built-in materials")')
     write(*,'("")')
     write(*,'("  ,----")')
     write(*,'("  | optool -c")')
     write(*,'("   ----")')
     write(*,'("")')
     write(*,'("  Add a water ice mantle (built-in data from Warren+08) that is 20% of")')
     write(*,'("  the core mass")')
     write(*,'("")')
     write(*,'("  ,----")')
     write(*,'("  | optool pyr-mg70 0.87  c 0.13  -m h2o-w 0.2  -p 0.25")')
     write(*,'("   ----")')
     write(*,'("")')
     write(*,'("  Like the previous example, but use ice refractive index data from a")')
     write(*,'("  separate file.")')
     write(*,'("")')
     write(*,'("  ,----")')
     write(*,'("  | optool pyr-mg70 0.87  c 0.13  -p 0.25  -m data/ice_hudgins.dat 0.2")')
     write(*,'("   ----")')
     write(*,'("")')
     write(*,'("  Pure water ice grains in a narrow size distribution from 1 to 3")')
     write(*,'("  microns, with 15 sample sizes following an $f(a)\propto a^{-2.5}$")')
     write(*,'("  powerlaw size distribution. Also, restrict the wavelength range to")')
     write(*,'("  10-100mum, and turn off DHS to get perfect spheres (Mie).")')
     write(*,'("")')
     write(*,'("  ,----")')
     write(*,'("  | optool h2o  -a 1 3 2.5 15  -l 10 100 -mie")')
     write(*,'("   ----")')
     write(*,'("")')
     write(*,'("  For silicon carbide, compute the opacity of a single grain size")')
     write(*,'("  (2.5mum) at lambda=8.9mum.")')
     write(*,'("")')
     write(*,'("  ,----")')
     write(*,'("  | optool -a 2.5 -l 8.9 sic")')
     write(*,'("   ----")')
     write(*,'("")')
     write(*,'("  Represent the default dust model (DIANA, you also get this when you do")')
     write(*,'("  not give any materials at all) in 42 grain sizes, and produce input")')
     write(*,'("  files for RADMC-3D, one for each grain size, with full scattering")')
     write(*,'("  matrix, chopping 3 degrees from the scattering peak.")')
     write(*,'("")')
     write(*,'("  ,----")')
     write(*,'("  | optool -na 42 -d -s -radmc -chop 3")')
     write(*,'("   ----")')
     write(*,'("")')
     write(*,'("  Use MMF to compute the opacities of dust aggregates made of pyroxene")')
     write(*,'("  monomers.  Use a monomer radius of 0.3 mum to construct aggregates")')
     write(*,'("  with compact-volume radii between 10 and 30 mum, and a fractal")')
     write(*,'("  dimension of 1.9.")')
     write(*,'("")')
     write(*,'("  ,----")')
     write(*,'("  | optool pyr  -a 10 30  -mmf 0.3 1.9")')
     write(*,'("   ----")')
     write(*,'("")')
     write(*,'("  Compute the CDE approximation of small graphite grains.")')
     write(*,'("")')
     write(*,'("  ,----")')
     write(*,'("  | optool gra  -a 0.01 0.1 -l 1 30 -cde")')
     write(*,'("   ----")')
     write(*,'("")')
     write(*,'("3 Installation")')
     write(*,'("==============")')
     write(*,'("")')
     write(*,'("  You can download, compile, and install  optool  with these simple")')
     write(*,'("  steps, using the freely available GNU FORTRAN compiler [ gfortran ].")')
     write(*,'("")')
     write(*,'("  ,----")')
     write(*,'("  | git clone https://github.com/cdominik/optool.git        # clone repository")')
     write(*,'("  | cd optool                      # enter code directory")')
     write(*,'("  | make multi=true                # compile with multicore support")')
     write(*,'("  | make install bindir=~/bin/     # copy the binaries to binary path")')
     write(*,'("  | pip install -e .               # install the python module (with the dot!)")')
     write(*,'("   ----")')
     write(*,'("")')
     write(*,'("  In the compilation step, use  multi=true  to add multicore support")')
     write(*,'("  (recommended!),  ifort=true  to use the [Intel fortran compiler]")')
     write(*,'("  instead of  gfortran , and  fits=true  to add support for writing FITS")')
     write(*,'("  files[1]. The executable is called  optool . The  make install  step")')
     write(*,'("  copies it and also  optool2tex  and  optool-complete  into  bindir .")')
     write(*,'("")')
     write(*,'("  If compiling the code is a problem, use the [binaries for Mac and")')
     write(*,'("  Linux] we provide. For shell command line completion support, check")')
     write(*,'("  the file  optool-complete .")')
     write(*,'("")')
     write(*,'("4 Command line arguments")')
     write(*,'("========================")')
     write(*,'("")')
  endif
  if((what.eq.'-h').or.(what.eq.'all')) then
     write(*,'("   -h [OPT] ")')
     write(*,'("        Show command line options or specific information about option")')
     write(*,'("        * -OPT *.")')
  endif
  if((what.eq.'-q').or.(what.eq.'all')) then
     write(*,'("   -q ")')
     write(*,'("        Reduce output to STDOUT to essential warnings and errors.")')
     write(*,'("")')
  endif
  if(what.eq.'all') then
     write(*,'("4.1 Grain composition")')
     write(*,'("~~~~~~~~~~~~~~~~~~~~~")')
     write(*,'("")')
     write(*,'("  If no composition is specified, the default is *-c pyr 0.87 -c c 0.13")')
     write(*,'("  -p 0.25*.")')
     write(*,'("")')
  endif
  if((what.eq.'-c').or.(what.eq.'all')) then
     write(*,'("   -c ")')
     write(*,'("        List available built-in materials (the keys for the *-c* and")')
     write(*,'("        *-m* options).")')
     write(*,'("")')
  endif
  if((what.eq.'-c').or.(what.eq.'all')) then
     write(*,'("   [-c] KEY-or-FILE [MFRAC] ")')
     write(*,'("          Specify a material to include in the grain.   KEYorFILE  can")')
     write(*,'("        be the [key for a builtin material], or the [path to an  lnk ")')
     write(*,'("        file].  MFRAC  is the /mass/ fraction (default 1.0) of the")')
     write(*,'("        material. You can give up to 20 materials to build up the grain.")')
     write(*,'("        Mass fractions do not have to add up to one, they will be")')
     write(*,'("        renormalized.  All materials will be mixed together using the")')
     write(*,'("        /Bruggeman/ rule, and vacuum can be added through the")')
     write(*,'("        porosity. A *-c* switch before each  KEY-or-FILE  is optional.")')
     write(*,'("")')
  endif
  if((what.eq.'-m').or.(what.eq.'all')) then
     write(*,'("   -m KEY-or-FILE [MFRAC] ")')
     write(*,'("          Like *-c*, but place this material into the grain")')
     write(*,'("        mantle. Multiple mantle materials will be mixed using the")')
     write(*,'("        Bruggeman rule, and than that mix will be added to the core")')
     write(*,'("        using the /Maxwell-Garnett/ rule.  The *-m* is /not/ optional,")')
     write(*,'("        it must be present.")')
     write(*,'("")')
  endif
  if((what.eq.'-p').or.(what.eq.'all')) then
     write(*,'("   -p POROSITY [P_MANTLE] ")')
     write(*,'("          Porosity, the /volume/ fraction of vacuum, a number smaller")')
     write(*,'("        than 1.  The default is 0.  A single value will apply to both")')
     write(*,'("        core and mantle, but a second value will be specific for the")')
     write(*,'("        mantle (and may be 0).")')
     write(*,'("")')
  endif
  if(what.eq.'all') then
     write(*,'("4.2 Grain geometry and computational method")')
     write(*,'("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")')
     write(*,'("")')
     write(*,'("  If no method is explicitly specified, the default is *-dhs 0.8*, i.e.")')
     write(*,'("  DHS with f_max=0.8.")')
     write(*,'("")')
  endif
  if((what.eq.'-dhs').or.(what.eq.'all')) then
     write(*,'("   -dhs [FMAX] ")')
     write(*,'("          Use the /Distribution of Hollow Spheres/ (DHS, Min+ 2005)")')
     write(*,'("        approach to model deviations from perfect spherical symmetry and")')
     write(*,'("        low-porosity aggregates. Spheres with inner holes with volume")')
     write(*,'("        fractions between 0 and f_max (default 0.8) are averaged to")')
     write(*,'("        mimic irregularities.  f_max=0 means to use solid spheres (Mie")')
     write(*,'("        theory), i.e. perfectly regular grains. For backward")')
     write(*,'("        compatibility, *-fmax* can be used instead of *-dhs*.")')
     write(*,'("")')
  endif
  if((what.eq.'-mmf').or.(what.eq.'all')) then
     write(*,'("   -mmf [A0 [DFRAC-OR-FILL [KF]]] ")')
     write(*,'("          Use /Modified Mean Field/ theory (MMF, Tazaki & Tanaka 2018)")')
     write(*,'("        to compute opacities of highly porous or fractal aggregates.")')
     write(*,'("        *-c*, *-m*, and *-p* determine the composition of monomers with")')
     write(*,'("        radius  A0  (default 0.1mum).  Particles will be aggregates with")')
     write(*,'("        a /compact size/ given by the *-a* switch, giving rise to")')
     write(*,'("        $N=a^3/a_0^3$ monomers.  DFRAC-OR-FILL  specifies either the")')
     write(*,'("        fractal dimension (if >1) or the /volume filling factor/ (if")')
     write(*,'("        <1). The default is 0.2. KF may be used to change the default")')
     write(*,'("        prefactor.")')
     write(*,'("")')
  endif
  if((what.eq.'-mie').or.(what.eq.'all')) then
     write(*,'("   -mie ")')
     write(*,'("          Do a standard /Mie/ calculation for perfect spheres. This is")')
     write(*,'("        short for *-dhs 0* .")')
     write(*,'("")')
  endif
  if((what.eq.'-cde').or.(what.eq.'all')) then
     write(*,'("   -cde ")')
     write(*,'("          Compute CDE (continuous distribution of ellipsoids) Rayleigh")')
     write(*,'("        limit opacities.")')
     write(*,'("")')
  endif
  if(what.eq.'all') then
     write(*,'("4.3 Grain size distribution")')
     write(*,'("~~~~~~~~~~~~~~~~~~~~~~~~~~~")')
     write(*,'("")')
  endif
  if((what.eq.'-a').or.(what.eq.'-amin').or.(what.eq.'-amax').or.(what.eq.'-apow').or.(what.eq.'-na').or.(what.eq.'all')) then
     write(*,'("   -a AMIN [AMAX [APOW [NA]]] ")')
     write(*,'("          Specify (minimum) grain radius, and optionally maximum grain")')
     write(*,'("        radius, the size distribution powerlaw and the number of size")')
     write(*,'("        bins.  You may also use options to set individual values with")')
     write(*,'("        *-amin*, *-amax*, *-apow*, *-na*. The defaults are 0.05 mum,")')
     write(*,'("        3000 mum, 3.5, and /10 per size decade with a fixed minimum of")')
     write(*,'("        5/, respectively.")')
     write(*,'("         >  If only a single size is specified with *-a*, then")')
     write(*,'("        a_max=a_min and n_a=1 are implied.")')
     write(*,'("         >  If a_max is negative, the range will be $a_{\rm min}\pm")')
     write(*,'("        a_{\rm max}$, and a_pow defaults to 0.")')
     write(*,'("")')
  endif
  if(what.eq.'all') then
     write(*,'("4.4 Wavelength grid")')
     write(*,'("~~~~~~~~~~~~~~~~~~~")')
     write(*,'("")')
  endif
  if((what.eq.'-l').or.(what.eq.'-lmin').or.(what.eq.'-lmax').or.(what.eq.'-nl').or.(what.eq.'-nlam').or.(what.eq.'all')) then
     write(*,'("   -l LMIN [LMAX [NLAM]] ")')
     write(*,'("          Specify the (minimum) wavelength, and optionally the maximum")')
     write(*,'("        wavelength and the number of wavelengths points for the")')
     write(*,'("        construction of the wavelength grid.  The default values are")')
     write(*,'("        0.05 mum, 10000 mum, and 300, respectively.  You may also use")')
     write(*,'("        the options *-lmin*, *-lmax*, and *-nlam* (or *-nl*) to set")')
     write(*,'("        individual values.")')
     write(*,'("         >  If only one wavelength is specified with *-l*, then")')
     write(*,'("        lambda_max=lambda_min and n_lambda=1 are implied.")')
     write(*,'("")')
  endif
  if((what.eq.'-l').or.(what.eq.'-lmin').or.(what.eq.'-lmax').or.(what.eq.'-nl').or.(what.eq.'-nlam').or.(what.eq.'all')) then
     write(*,'("   -l FILE ")')
     write(*,'("          Read the wavelength grid from  FILE .  The file may start with")')
     write(*,'("        comment lines, and the first non-comment line needs to contain")')
     write(*,'("        the number of wavelength values in the data block below it. In")')
     write(*,'("        the data block, the first column is expected to hold the")')
     write(*,'("        wavelength values, in mum. In particular, an [ lnk ] file could")')
     write(*,'("        be used here.")')
     write(*,'("")')
  endif
  if(what.eq.'all') then
     write(*,'("4.5 Controlling the output")')
     write(*,'("~~~~~~~~~~~~~~~~~~~~~~~~~~")')
     write(*,'("")')
     write(*,'("  The standard output is the file [ dustkappa.dat ], with the opacities")')
     write(*,'("  and the asymmetry parameter /g/. The following options control and")')
     write(*,'("  extend the [output].")')
     write(*,'("")')
  endif
  if((what.eq.'-o').or.(what.eq.'all')) then
     write(*,'("   -o [DIR] ")')
     write(*,'("          Put the output files in directory  DIR  instead of the current")')
     write(*,'("        working directory.  ./output  will be used if *-o* is present")')
     write(*,'("        but  DIR  is not specified.")')
     write(*,'("")')
  endif
  if((what.eq.'-s').or.(what.eq.'all')) then
     write(*,'("   -s [NANG] ")')
     write(*,'("          Include the full scattering matrix in the output.  NANG  can")')
     write(*,'("        optionally specify the number of equally-spaced [angular grid")')
     write(*,'("        points] to cover the range of angles between 0 and 180 degrees.")')
     write(*,'("        The default for  NANG  is 180 and should normally be just fine.")')
     write(*,'("")')
  endif
  if((what.eq.'-d').or.(what.eq.'all')) then
     write(*,'("   -d [NSUB] ")')
     write(*,'("          Divide the computation up into n_a parts to produce a file for")')
     write(*,'("        each grain size.  Each size will be an average over a range of")')
     write(*,'("         NSUB  (default 5) grains around the real size.")')
     write(*,'("")')
  endif
  if((what.eq.'-chop').or.(what.eq.'all')) then
     write(*,'("   -chop [NDEG] ")')
     write(*,'("          Cap the first  NDEG  (2 if unspecified) degrees of the")')
     write(*,'("        [forward scattering peak].")')
     write(*,'("")')
  endif
  if((what.eq.'-fits').or.(what.eq.'all')) then
     write(*,'("   -fits ")')
     write(*,'("          Write [ dustkappa.fits ] instead of ASCII output.  With  -d ,")')
     write(*,'("        write n_a files.")')
     write(*,'("")')
  endif
  if((what.eq.'-radmc').or.(what.eq.'all')) then
     write(*,'("   -radmc [LABEL] ")')
     write(*,'("          RADMC-3D uses a different angular grid and [scattering matrix]")')
     write(*,'("        normalization. File names will contain  LABEL  if specified and")')
     write(*,'("        have the extension  .inp .")')
     write(*,'("")')
  endif
  if((what.eq.'-print').or.(what.eq.'all')) then
     write(*,'("   -print [VAR] ")')
     write(*,'("          Write to  STDOUT  instead of files. The default is to write")')
     write(*,'("        lambda, kappa_abs, kappa_sca, kappa_ext, and g. When  VAR  is")')
     write(*,'("        any of  kabs ,  ksca ,  kext , or  g , write only that, without")')
     write(*,'("        header. You can use this to extract a single value, for example")')
     write(*,'("        the 850mum extinction opacity of grains between 1 and 3mm:")')
     write(*,'("         optool -a 1000 3000 -l 850 -print kext ")')
     write(*,'("")')
  endif
  if(what.eq.'all') then
     write(*,'("5 Material properties")')
     write(*,'("=====================")')
     write(*,'("")')
     write(*,'("   optool  needs refractive index data to work.  For your convenience, a")')
     write(*,'("  useful list of materials is compiled into  optool . You can also find")')
     write(*,'("  and use other data.  No matter where the data is from, you should")')
     write(*,'("  /always/ cite the original laboratory papers.")')
     write(*,'("")')
     write(*,'("5.1 Built-in materials")')
     write(*,'("~~~~~~~~~~~~~~~~~~~~~~")')
     write(*,'("")')
     write(*,'("  To access one of the built-in materials, specify the corresponding key")')
     write(*,'("  string like  pyr-mg70 . In each material class we have selected a")')
     write(*,'("  useful default, accessible with an even simpler generic key (for")')
     write(*,'("  example,  pyr  is an alias for  pyr-mg70 ). Most of the built-in")')
     write(*,'("  refractive index datasets have a reasonably wide wavelength coverage -")')
     write(*,'("  the few exceptions are highlighted by bold-face numbers.  If a")')
     write(*,'("  material is being used outside of the measured region,  optool  will")')
     write(*,'("  still function, using extrapolated optical properties.")')
     write(*,'("")')
     write(*,'("  Even the limited number of materials we have selected to include with")')
     write(*,'("   optool  can be daunting. To get started with some kind of standard")')
     write(*,'("  opacity, we recommend to work with pyroxene \fbox{pyr}, carbon")')
     write(*,'("  \fbox{c}, and (at low temperaturs) water ice \fbox{h2o}.")')
     write(*,'("")')
     write(*,'("  -c Key      -c Key       Material                 State  Reference     ")')
     write(*,'(" generic     full key                                                    ")')
     write(*,'("---------------------------------------------------------- --------------")')
     write(*,'("             pyr-mg100    MgSiO_3                  amorph  Dorschner+95")')
     write(*,'("             pyr-mg95     Mg_0.95  Fe_0.05  SiO_3  amorph  Dorschner+95")')
     write(*,'("             pyr-mg80     Mg_0.8  Fe_0.2  SiO_3    amorph  Dorschner+95")')
     write(*,'("      pyr    pyr-mg70     Mg_0.7  Fe_0.3  SiO_3    amorph  Dorschner+95")')
     write(*,'("             pyr-mg60     Mg_0.6  Fe_0.4  SiO_3    amorph  Dorschner+95")')
     write(*,'("             pyr-mg50     Mg_0.5  Fe_0.5  SiO_3    amorph  Dorschner+95")')
     write(*,'("             pyr-mg40     Mg_0.4  Fe_0.6  SiO_3    amorph  Dorschner+95")')
     write(*,'(" ens         pyr-c-mg96   Mg_0.96  Fe_0.04  SiO3   cryst   Jäger+98")')
     write(*,'("---------------------------------------------------------- --------------")')
     write(*,'(" ol          ol-mg50      MgFeSiO_4                amorph  Dorschner+95")')
     write(*,'("             ol-mg40      Mg_0.8  Fe_1.2  SiO_4    amorph  Dorschner+95")')
     write(*,'(" for         ol-c-mg100   Mg_2  SiO_4              cryst   Suto+06")')
     write(*,'("             ol-c-mg95    Mg_1.9  Fe_0.1  SiO_4    cryst   Fabian+01")')
     write(*,'(" fay         ol-c-mg00    Fe_2  SiO_4              cryst   Fabian+01")')
     write(*,'("---------------------------------------------------------- --------------")')
     write(*,'("             astrosil     MgFeSiO_4                mixed   Draine+03")')
     write(*,'("---------------------------------------------------------- --------------")')
     write(*,'("      c      c-z          C                        amorph? Zubko+96")')
     write(*,'("             c-p          C                        amorph  Preibisch+93")')
     write(*,'(" gra         c-gra        C graphite               cryst   Draine+03")')
     write(*,'(" org         c-org        CHON organics            amorph  Henning+96")')
     write(*,'("             c-nano       C nano-diamond           cryst   Mutschke+04")')
     write(*,'("---------------------------------------------------------- --------------")')
     write(*,'(" iron        fe-c         Fe                       metal   Henning+96")')
     write(*,'("             fes          FeS                      metal   Henning+96")')
     write(*,'("             sic          SiC                      cryst   Laor93")')
     write(*,'("---------------------------------------------------------- --------------")')
     write(*,'(" qua         sio2         SiO_2                    amorph  Kitamura+07")')
     write(*,'(" cor         cor-c        Al_2  O_3                cryst   Koike+95")')
     write(*,'("---------------------------------------------------------- --------------")')
     write(*,'("      h2o    h2o-w        Water ice                cryst   Warren+08")')
     write(*,'("             h2o-a        Water ice                amorph  Hudgins+93")')
     write(*,'(" co2         co2-w        CO_2 ice                 cryst   Warren+86")')
     write(*,'(" nh3         nh3-m        NH_3 ice                 cryst   Martonchik+83")')
     write(*,'(" co          co-a         CO ice                   amorph  Palumbo+06")')
     write(*,'("             co2-a / c    CO_2 ice                 am / cr Gerakines+20")')
     write(*,'("             ch4-a / c    CH_4 ice                 am / cr Gerakines+20")')
     write(*,'("             ch3oh-a / c  CH_3  OH ice             am / cr Gerakines+20")')
     write(*,'("")')
     write(*,'("5.2 External refractory index files ( lnk  files)")')
     write(*,'("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")')
     write(*,'("")')
     write(*,'("   optool  can use external refractive index data in files with the")')
     write(*,'("  following format:")')
     write(*,'("  - The file may start with several comment lines (lines starting with")')
     write(*,'("     ! ,  # , or  * ).")')
     write(*,'("  - The next line contains two numbers, the number of wavelengths")')
     write(*,'("    $n_\lambda$ and the specific density rho of the material in")')
     write(*,'("    g/cm^{3}.")')
     write(*,'("  - The remaining lines should form three columns of data: lambda[mum]")')
     write(*,'("    (sorted either up or down), and the real and imaginary parts of the")')
     write(*,'("    refractive index, $n$ and $k$.")')
     write(*,'("")')
     write(*,'("  More data ready for use with  optool  is in [this repository]. Other")')
     write(*,'("  resources are the [Jena database], [ARIA] and original papers in the")')
     write(*,'("  literature. Don t forget to add the line with $n_\lambda$ and rho!  If")')
     write(*,'("  that is not possible,  optool  will count the lines and you can")')
     write(*,'("  specify the density after the mass fraction, like this:  optool -c")')
     write(*,'("  path/to/file.lnk 0.7 3.42 .")')
     write(*,'("")')
     write(*,'("6 Output files")')
     write(*,'("==============")')
     write(*,'("")')
     write(*,'("  dustkappa.dat")')
     write(*,'("          This is an ASCII file containing the basic opacity results. It")')
     write(*,'("        starts with a comment section describing the dust model and also")')
     write(*,'("        showing the exact command line that was used to produce the")')
     write(*,'("        file.  The header is followed by the format number (3,")')
     write(*,'("        currently), followed by the number of wavelengths in the grid,")')
     write(*,'("        both on lines by themselves.  Then follows a block with these")')
     write(*,'("        columns:")')
     write(*,'("")')
     write(*,'("        1. wavelength lambda [micron]")')
     write(*,'("        2. mass absorption cross section kappa_abs [cm^2/g]")')
     write(*,'("        3. mass scattering cross section kappa_sca [cm^2/g]")')
     write(*,'("        4. asymmetry parameter /g/")')
     write(*,'("")')
     write(*,'("  dustkapscatmat.dat")')
     write(*,'("          ASCII file with cross sections and full scattering matrix. It")')
     write(*,'("        is an extended version of the  dustkappa.dat  file.  This file")')
     write(*,'("        has a format number (0), the number of wavelengths and then the")')
     write(*,'("        number of angular points after the comment section.  After an")')
     write(*,'("        empty line, the same opacity block as in  dustkappa.dat  is")')
     write(*,'("        present.  Another empty line is followed by a list of the grid")')
     write(*,'("        angles, another empty line, and then the scattering matrix")')
     write(*,'("        elements for all wavelengths and all angles. The comment section")')
     write(*,'("        at the start of the file shows the structure in a formal way.")')
     write(*,'("        See [the appendix] for information about the normalization of")')
     write(*,'("        the scattering matrix and about the angular grid that is used")')
     write(*,'("        for it.  Also, see the  -radmc  switch which will modify[2] the")')
     write(*,'("        output to make sure it can be used as an input file for")')
     write(*,'("        [RADMC-3D].")')
     write(*,'("")')
     write(*,'("  dustkappa.fits")')
     write(*,'("          The FITS-file (ending in ’.fits’) is written instead of the")')
     write(*,'("        ASCII output when using the  -fits  switch. It has two HDU")')
     write(*,'("        blocks. The first block contains the cross sections per unit")')
     write(*,'("        mass. This is an n_lambda * 4 matrix with these columns:")')
     write(*,'("")')
     write(*,'("        - wavelength in [micron]")')
     write(*,'("        - kappa_ext, kappa_abs, kappa_sca, all in [cm^2/g]")')
     write(*,'("")')
     write(*,'("        The second block contains the scattering matrix elements. It is")')
     write(*,'("        a n_lambda * 6 * n_ang matrix, containing the 6 elements of the")')
     write(*,'("        scattering matrix for n_ang equidistant scattering angles from")')
     write(*,'("        forward scattering (element 0) to backward scattering (element")')
     write(*,'("        n_ang-1), for each lambda. The matrix elements are F_11, F_12,")')
     write(*,'("        F_22, F_33, F_34, and F_44.")')
     write(*,'("")')
     write(*,'("  optool.tex")')
     write(*,'("          As a little gimmick, you can run  optool2tex  with the exact")')
     write(*,'("        same command line arguments as used in an  optool ")')
     write(*,'("        run.  optool.tex  then contains text and a table, describing the")')
     write(*,'("        methods used for the opacity computation and listing the")')
     write(*,'("        composition of the grains. All relevant references are given -")')
     write(*,'("        the BibTeX file  optool.bib  is required for the file to be")')
     write(*,'("        processed properly. You can rework this text to include it into")')
     write(*,'("        your paper. For more details, read the comment section in")')
     write(*,'("         optool2tex .")')
     write(*,'("")')
     write(*,'("7 Python interface")')
     write(*,'("==================")')
     write(*,'("")')
     write(*,'("   optool  comes with a [ python ] module  optool.py  that runs  optool ")')
     write(*,'("  in the background[3] and puts all computed quantities as  numpy ")')
     write(*,'("  arrays into a python object.  This makes it straight forward to")')
     write(*,'("  inspect and further process the output. Here is how to use it:")')
     write(*,'("")')
     write(*,'("  ,----")')
     write(*,'("  | import optool")')
     write(*,'("  | p = optool.particle( ~/bin/optool pyr 0.8 -m ice 0.2 -na 24 -d )")')
     write(*,'("   ----")')
     write(*,'("")')
     write(*,'("  The argument to  optool.particle()  must be a valid shell command[4]")')
     write(*,'("  to run  optool , if necessary with the full path to the  optool ")')
     write(*,'("  binary.  Depending on the presence of the  optool  s *-d* switch, the")')
     write(*,'("  command will produce opacities either for $n_p=1$ particle, or for")')
     write(*,'("  $n_p=n_a$ particles. Most of the attributes (with the exception of the")')
     write(*,'("  global wavelength and angular grids) will therefore be arrays with the")')
     write(*,'("  first dimension equal to $n_p$, even if $n_p=1$. The resulting object")')
     write(*,'("  will have the following attributes:")')
     write(*,'("")')
     write(*,'("   *Attribute*         *Type/Shape*           *Quantity*                                      ")')
     write(*,'("  --------------------------------------------------------------------------------------------")')
     write(*,'("    cmd                 string                The full command given in the particle() call   ")')
     write(*,'("  --------------------------------------------------------------------------------------------")')
     write(*,'("    radmc               boolean               Output follows RADMC conventions                ")')
     write(*,'("    scat                boolean               Scattering matrix is available                  ")')
     write(*,'("  --------------------------------------------------------------------------------------------")')
     write(*,'("    nlam                int                   Number of wavelength points                     ")')
     write(*,'("    lam                 float[nlam]           The wavelength grid                             ")')
     write(*,'("    nang                int                   Number of scattering angles                     ")')
     write(*,'("    scatang             float[nang]           The angular grid                                ")')
     write(*,'("  --------------------------------------------------------------------------------------------")')
     write(*,'("    materials           [[[...]...]... ]      Lists with [location,m_{frac},rho,material]     ")')
     write(*,'("  --------------------------------------------------------------------------------------------")')
     write(*,'("    np                  int                   Number of particles, either 1 or (with -d) n_a  ")')
     write(*,'("  --------------------------------------------------------------------------------------------")')
     write(*,'("    fmax                float[np]             Maximum volume fraction of vacuum for DHS       ")')
     write(*,'("    pcore ,  pmantle    float[np]             Porosity of the core/mantle material            ")')
     write(*,'("  --------------------------------------------------------------------------------------------")')
     write(*,'("    amin ,  amax        float[np]             min/max grain size used for each particle       ")')
     write(*,'("    nsub                int[np]               Number of sizes averaged for each particle      ")')
     write(*,'("    apow                float[np]             Negative size distribution power law (e.g. 3.5) ")')
     write(*,'("    a1 ,  a2 ,  a3      float[np]             Mean <a>, $\sqrt{<a^2>}$, and $\sqrt[3]{<a^3>}$ ")')
     write(*,'("    rho                 float[np]             Specific density of grains                      ")')
     write(*,'("  --------------------------------------------------------------------------------------------")')
     write(*,'("    kabs,ksca,kext      float[np,nlam]        Absorption,scattering,extinction cross section  ")')
     write(*,'("    gsca                float[np,nlam]        Asymmetry parameter                             ")')
     write(*,'("  --------------------------------------------------------------------------------------------")')
     write(*,'("    f11 , ...,  f44     float[np,nlam,nang]   Scattering matrix element F_11, ... ,F_44       ")')
     write(*,'("    chop                float[np]             Degrees chopped off forward scattering          ")')
     write(*,'("  --------------------------------------------------------------------------------------------")')
     write(*,'("    plot()              method                Plot the cross sections and matrix elements     ")')
     write(*,'("  --------------------------------------------------------------------------------------------")')
     write(*,'("    computemean()       method                Compute Planck/Rosseland mean opacities         ")')
     write(*,'("    tmin,tmax,ntemp     float,float,int       Temperature grid for mean opacities             ")')
     write(*,'("    temp                float[ntemp]          Temperatures used for mean opacities            ")')
     write(*,'("    kplanck,kross       float[np,ntemp]       Mean opacities, after calling  computemean()    ")')
     write(*,'("  --------------------------------------------------------------------------------------------")')
     write(*,'("    norm                string                Current scattering matrix normalization         ")')
     write(*,'("    scatnorm()          method                Check/change scat. matrix normalization         ")')
     write(*,'("  --------------------------------------------------------------------------------------------")')
     write(*,'("    sizedist()          method                Sum opacities over a size distribution          ")')
     write(*,'("")')
     write(*,'("  [./maint/inspect.png]")')
     write(*,'("")')
     write(*,'("  Applying the  plot()  method to a  particle  object like  p.plot() ")')
     write(*,'("  will produce these plots:")')
     write(*,'("  - a plot showing the opacities kappa_abs, kappa_sca, and kappa_ext as")')
     write(*,'("    a function of wavelength, along with the asymmetry parameter /g/ (on")')
     write(*,'("    a linear y-scale).  Note that the blue /g/ curve does not have its")')
     write(*,'("    own axis, imagine the full /y/ axis going from 0 to 1 for /g/.")')
     write(*,'("  - a plot showing the scattering matrix elements as a function of")')
     write(*,'("    scattering angle, with sliders to go through grain sizes and")')
     write(*,'("    wavelengths.  When interpreting the y axis, note that we plot the")')
     write(*,'("    positive/negative $\log_{10}$ of positive/negative matrix elements,")')
     write(*,'("    compressing the range from $10^{-2}$ to $10^2$ into a line (use the")')
     write(*,'("    grey lines as a guide, ignore the y-axis labels).")')
     write(*,'("  - If the  computemean  method has been called first, the mean")')
     write(*,'("    opacities kappa_Planck and kappa_Ross are shown in a separate plot.")')
     write(*,'("    The mean opacities are per unit of grain mass, so please apply a")')
     write(*,'("    dust-to-gas mass ratio to obtain opacities for a gas-dust mixture.")')
     write(*,'("")')
     write(*,'("  The python module has a few more tricks up its sleeve (for details")')
     write(*,'("  check the documentation inside the Python module file  optool.py ):")')
     write(*,'("")')
     write(*,'("  - A  lnktable  class to read, plot, modify and write  lnk  files.")')
     write(*,'("    ,----")')
     write(*,'("    | x = optool.lnktable( lnk_data/sio2-Kitamura2007.lnk )")')
     write(*,'("    | x.plot()")')
     write(*,'("     ----")')
     write(*,'("")')
     write(*,'("  - Compute Planck and Rosseland mean opacities")')
     write(*,'("    ,----")')
     write(*,'("    | p = optool.particle( optool  pyr 0.87  c 0.13 -p 0.25 )")')
     write(*,'("    | p.computemean(tmin=10.,tmax=1500.,ntemp=300)")')
     write(*,'("     ----")')
     write(*,'("")')
     write(*,'("  - /Particle arithmetic/: multiplying  optool.particle  objects with")')
     write(*,'("    factors and adding them, or applying size distributions to a")')
     write(*,'("    pre-computed set of opacities. The following page contains a number")')
     write(*,'("    of examples.")')
     write(*,'("")')
     write(*,'("  Compute the opacities of 100 olivine silicate grain sizes and of 50")')
     write(*,'("  carbon grain sizes, and store the opacities in cache directories. This")')
     write(*,'("  works by specifying the directory as the second argument. In a new")')
     write(*,'("  session, if the directories still exist and were produced using the")')
     write(*,'("  same commands, the opacities are simply read back in.")')
     write(*,'("")')
     write(*,'("  ,----")')
     write(*,'("  | import optool")')
     write(*,'("  | import numpy as np")')
     write(*,'("  | sil  = optool.particle( optool -d -a 0.001 100 0 100 ol-mg50 ,cache= sil )")')
     write(*,'("  | carb = optool.particle( optool -d -a 0.001 3.0 0 50  c ,cache= carb )")')
     write(*,'("   ----")')
     write(*,'("")')
     write(*,'("  Apply powerlaw size distributions, and limit the size of the")')
     write(*,'("  contributing grains.  Note that a power law f(a)[proportional to]")')
     write(*,'("  a^{-3.5} implies using a power a^{-2.5} when computing the number of")')
     write(*,'("  particles per size bin on a logarithmic size grid. No normalization is")')
     write(*,'("  necessary - the  sizedist  method will take care of that.")')
     write(*,'("")')
     write(*,'("  ,----")')
     write(*,'("  | nsil = sil.a1**(-2.5)             # power law, no normalization required")')
     write(*,'("  | nsil[sil.a1<0.01] = 0             # no grains smaller than 0.01um")')
     write(*,'("  | nsil[sil.a1>0.3]  = 0             # no grains larger  than 0.3um")')
     write(*,'("  | sil_pl = sil.sizedist(nsil)       # pass the relative number for each size")')
     write(*,'("  | ")')
     write(*,'("  | nc = carb.a1**(-2.5)              # power law, no normalization required")')
     write(*,'("  | nc[carb.a1>0.3]=0                 # no grains larger than 0.3um")')
     write(*,'("  | carb_pl = carb.sizedist(nc)       # pass the relative number for each size")')
     write(*,'("   ----")')
     write(*,'("")')
     write(*,'("   sil_pl  and  carb_pl  are now objects with a single opacity each,")')
     write(*,'("  obtained by adding opacities with the weights of the size")')
     write(*,'("  distribution. The opacities are still per g of total grain mass.")')
     write(*,'("  Let s add these two opacities with mass weights, to get something")')
     write(*,'("  resembling an interstellar dust opacity produced by a mixture of")')
     write(*,'("  silicate and carbon grains:")')
     write(*,'("  ,----")')
     write(*,'("  | ptot = 0.7*sil_pl + 0.3*carb_pl   # weights should add up to 1")')
     write(*,'("  | ptot.plot()                       # plot the resulting opacity")')
     write(*,'("   ----")')
     write(*,'("")')
     write(*,'("  Now let s assume we are looking at an interstellar cloud, where the")')
     write(*,'("  dust is just one percent of the total mass.  We want to have the")')
     write(*,'("  opacity per unit of /gas mass/ instead, and we need Planck and")')
     write(*,'("  Rosseland mean opacities:")')
     write(*,'("  ,----")')
     write(*,'("  | p_ism = ptot * 0.01               # dilute the opacity")')
     write(*,'("  | p_ism.computemean(tmax=1300)      # Compute mean opacities")')
     write(*,'("  | p_ism.plot()                      # Plot the results")')
     write(*,'("   ----")')
     write(*,'("")')
     write(*,'("  Other size distributions can be made just as easily.  Here is a")')
     write(*,'("  log-normal size distribution for the silicate grains, with a peak")')
     write(*,'("  abundance at a size of a_m=1.3 microns, and a logarithmic width of")')
     write(*,'("  sigma=0.2:")')
     write(*,'("  ,----")')
     write(*,'("  | sil_ln = sil.sizedist( np.exp(-0.5* (np.log(sil.a1/1.3)/0.2)**2) )")')
     write(*,'("  | sil_ln.write( dkap_ln.dat )       # write opacity to a file")')
     write(*,'("   ----")')
     write(*,'("")')
     write(*,'("8 Units")')
     write(*,'("=======")')
     write(*,'("")')
     write(*,'("  Due to conventions in our field, the input and output of  optool  uses")')
     write(*,'("  the following units")')
     write(*,'("  - *microns* for grain sizes and wavelengths.[5]")')
     write(*,'("  - *g/cm^3* for mass densities of materials")')
     write(*,'("  - *cm^2 g^-1* for opacities kappa_abs, kappa_sca, and kappa_ext")')
     write(*,'("  - *sr^-1* or *cm^2 g^-1 sr^-1* for the scattering matrix elements, see")')
     write(*,'("    below.")')
     write(*,'("")')
     write(*,'("9 Scattering Matrix: The fine print")')
     write(*,'("===================================")')
     write(*,'("")')
     write(*,'("9.1 Phase function normalization")')
     write(*,'("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~")')
     write(*,'("")')
     write(*,'("  A number of different normalizations for the scattering matrix are")')
     write(*,'("  being used in the literature and in computational tools. The")')
     write(*,'("  differences are significant, and it is important to be aware of the")')
     write(*,'("  choice. For  optool  we are using a convention ([Hovenier (2004)]) in")')
     write(*,'("  which the average over all directions of the 1-1 element of the")')
     write(*,'("  scattering matrix equals unity, i.e. the integral will be 4pi:")')
     write(*,'("")')
     write(*,'("  \begin{equation}")')
     write(*,'("  \label{eq:1}")')
     write(*,'("  \oint_{(4\pi)} F_{11}(\lambda,\Theta) d\Omega = ")')
     write(*,'("  2\pi \int_{-1}^{1} F_{11}(\lambda,\mu) {\rm d}\mu= 4\pi \quad ,")')
     write(*,'("  \end{equation}")')
     write(*,'("")')
     write(*,'("  with $\mu=\cos\Theta$.  optool  can also produce output for [RADMC-3D]")')
     write(*,'("  which uses instead")')
     write(*,'("")')
     write(*,'("  \begin{equation}")')
     write(*,'("  \label{eq:2}")')
     write(*,'("  \oint_{(4\pi)} Z_{11}(\lambda,\Theta) d\Omega =")')
     write(*,'("  2\pi \int_{-1}^{1} Z_{11}(\lambda,\mu) {\rm d}\mu =")')
     write(*,'("   \kappa_{\rm sca}(\lambda) \quad .")')
     write(*,'("  \end{equation}")')
     write(*,'("")')
     write(*,'("  The books by Bohren & Huffman and by Mishchenko use different")')
     write(*,'("  normalizations again. You can change the normalization of the")')
     write(*,'("  scattering matrix in the python interface with the  scatnorm() ")')
     write(*,'("  method. By default, that method checks the current normalization.")')
     write(*,'("  Using an argument   r  ,   b  ,   m  , or   h   will modify the")')
     write(*,'("  normalization.")')
     write(*,'("")')
     write(*,'("9.2 Forward-scattering peak")')
     write(*,'("~~~~~~~~~~~~~~~~~~~~~~~~~~~")')
     write(*,'("")')
     write(*,'("  Particles that are much larger than the wavelength of the considered")')
     write(*,'("  radiation can show extreme forward scattering, where much of the")')
     write(*,'("  /scattered/ radiation is sent into just a few degrees around the")')
     write(*,'("  forward direction.  This can be difficult to handle for radiative")')
     write(*,'("  transfer codes which have limited angular resolution or limited")')
     write(*,'("  sampling. [MCMax3D] has the  nspike  keyword to deal with this")')
     write(*,'("  issue. Other tools (e.g. RADMC-3D) require this to be taken care of by")')
     write(*,'("  the process that creates the opacity files.  The  -chop  switch")')
     write(*,'("  specifies a number of degrees around the forward scattering")')
     write(*,'("  direction. Inside that cone, the scattering matrix gets limited to the")')
     write(*,'("  value at the edge of the cone. To compensate and ensure energy")')
     write(*,'("  conservation, the scattering cross section will be reduced")')
     write(*,'("  accordingly. As a result, the radiation that would be /scattered/ into")')
     write(*,'("  this narrow range of angles will be treated as if it did have /no")')
     write(*,'("  interaction at all/ with the grain.")')
     write(*,'("")')
     write(*,'("9.3 Angular grid")')
     write(*,'("~~~~~~~~~~~~~~~~")')
     write(*,'("")')
     write(*,'("   optool  uses an angular grid in one-degree steps from 0 to 180")')
     write(*,'("  degrees.  The full degrees are the cell /interfaces/ of that")')
     write(*,'("  grid.  optool  computes the scattering matrix at the cell /midpoints/,")')
     write(*,'("  i.e. at 0.5degree, 1.5degree etc to 179.5degree, for a total of 180")')
     write(*,'("  values.  The scattering matrix is normalized in this way, so that a")')
     write(*,'("  numerical integral gives the correct result.")')
     write(*,'("")')
     write(*,'("  RADMC-3D requires the values of the scattering matrix on the cell")')
     write(*,'("  /boundaries/, so at 0degree, 1degree etc to 180degree, for a total of")')
     write(*,'("  181 values.  For the input files for RADMC-3D, we interpolate and")')
     write(*,'("  extend the computed values to the cell boundaries.")')
     write(*,'("")')
     write(*,'("10 Overview of optical properties")')
     write(*,'("=================================")')
     write(*,'("")')
     write(*,'("  This grid plot shows the imaginary parts of all built-in materials, in")')
     write(*,'("  the wavelength range from 0.05 to 300 mum.  Some if the ices have only")')
     write(*,'("  data in a small range, where the vibrational transitions lie.")')
     write(*,'("  However, these materials can be used over a much broader wavelength")')
     write(*,'("  range, because the extrapolation becomes problematic only in the UV")')
     write(*,'("  where electronic transitions kick in.")')
     write(*,'("")')
     write(*,'("  [./maint/all_k.pdf]")')
     write(*,'("")')
     write(*,'("11 How to ingest refractive index data for another material")')
     write(*,'("===========================================================")')
     write(*,'("")')
     write(*,'("  Using external refractive index data means that you have to keep track")')
     write(*,'("  of where those files are.  It can be convenient to compile your")')
     write(*,'("  favorite materials into  optool , so that accessing them will be as")')
     write(*,'("  simple as using the [built-in materials].  Here is how to do that:")')
     write(*,'("")')
     write(*,'("  1. Give your  lnk  file a name exactly like")')
     write(*,'("      pyr-mg70-Dorschner1995.lnk , where the start of the name")')
     write(*,'("     ( pyr-mg70 ) is the key to access the material and  Dorschner1995 ")')
     write(*,'("     (the text after the final  - ) is the reference.")')
     write(*,'("  2. Put this file into the  lnk_data  directory.")')
     write(*,'("  3. Optionally edit  lnk_data/lnk-help.txt , so that [ optool -c ] will")')
     write(*,'("     list the new material.  Note that, in order to define /generic")')
     write(*,'("     keys/, optool looks for pairs that look like  genkey -> fullkey  in")')
     write(*,'("     this file.")')
     write(*,'("  4. Run  make ingest  to update  optool_refind.f90 , now with your new")')
     write(*,'("     material.")')
     write(*,'("  5. Recompile and install the code.")')
     write(*,'("")')
     write(*,'("12 Internals")')
     write(*,'("============")')
     write(*,'("")')
     write(*,'("  This appendix describes some key aspects of the internal workings of")')
     write(*,'("  the code.")')
     write(*,'("")')
     write(*,'("  Refractive Index Data")')
     write(*,'("        Measured refractive index data is obtained from data compiled")')
     write(*,'("        into the code, or read-in from a file.  That data is then")')
     write(*,'("        interpolated and extrapolated onto the wavelength grid requested")')
     write(*,'("        for the computation. Extrapolation toward short wavelengths is")')
     write(*,'("        done keeping the refractive indices constant.  Extrapolation")')
     write(*,'("        toward long wavelengths assumes that the last two measured data")')
     write(*,'("        points define a powerlaw. Interpolation in the measured grid is")')
     write(*,'("        done using double-logarithmic interpolation.")')
     write(*,'("")')
     write(*,'("  Mixing")')
     write(*,'("        Once the refractive index for all involved materials is")')
     write(*,'("        available, the core and the mantle mixtures are created")')
     write(*,'("        independently, using the Bruggeman rule.  Mass fractions are")')
     write(*,'("        converted into volume fractions, and porosity is implemented")')
     write(*,'("        using vacuum as an additional material.  The subroutine doing")')
     write(*,'("        the mixing uses an iterative procedure that is very stable, also")')
     write(*,'("        for a large number of components.")')
     write(*,'("        If there is a mantle, the Maxwell Garnett rule is applied with")')
     write(*,'("        the core being treated as an inclusion inside a mantle matrix.")')
     write(*,'("")')
     write(*,'("  DHS")')
     write(*,'("        In order to simulate irregularities in grains (irregular shapes,")')
     write(*,'("        or the properties of low-porosity aggregates),  optool  averages")')
     write(*,'("        the opacities of grains with an inner empty region, over a range")')
     write(*,'("        of volume fractions of this inner region between 0 and $f_{\rm")')
     write(*,'("        max}$.  The subroutine used to compute the opacities and")')
     write(*,'("        scattering matrix elements for these structures is  DMiLay ")')
     write(*,'("        (Toon & Ackerman 1981).  When the size parameter $x=2 \pi")')
     write(*,'("        a/\lambda$ exceeds a value of 10^4, no DHS averaging is used.  A")')
     write(*,'("        standard Mie calculation is performed, using the routine")')
     write(*,'("         MeerhoffMie  (de Rooij+ 1984), for a fixed size parameter of")')
     write(*,'("        5000, with proper scaling to the actual size of the particle.")')
     write(*,'("")')
     write(*,'("  MMF")')
     write(*,'("        To construct fluffy/fractal aggregates,  optool  needs the")')
     write(*,'("        number of monomers $N$, the fractal dimension $D_{\rm f}$, and a")')
     write(*,'("        scaling factor $k_{\rm f}$ which are related to the radius of")')
     write(*,'("        gyration $R_{\rm g}$ of the aggregate by $N=k_{\rm f}(R_{\rm")')
     write(*,'("        g}/a_0)^{D_{\rm f}}$.  The size $a$ of the particles as")')
     write(*,'("        specified by the *-a* switch is interpreted as the /compact/[6]")')
     write(*,'("        size of all material in the aggregate, so that $N=a^3/a_0^3$,")')
     write(*,'("        where $a_0$ is the monomer radius.  The average volume filling")')
     write(*,'("        factor $f$ can be expressed by $f=N\cdot(\sqrt{3/5}\,a_0/R_{\rm")')
     write(*,'("        g})^3$.  To determine the structure of the aggregates, the user")')
     write(*,'("        can specify a structure parameter.  If that parameter is larger")')
     write(*,'("        than 1, it is interpreted as the /fractal dimension/ $D_{\rm")')
     write(*,'("        f}$.  Using a fixed fractal dimension means that the volume")')
     write(*,'("        filling factor will decrease with aggregate size.  As an")')
     write(*,'("        alternative, the structure parameter can be less than 1.  In")')
     write(*,'("        that case, it is interpreted as a fixed /volume filling factor/")')
     write(*,'("        $f$ that applies to all aggregate sizes - with the implication")')
     write(*,'("        that then the fractal dimension increases as a function of")')
     write(*,'("        size. The fractal prefactor $k_{\rm f}$ is chosen automatically")')
     write(*,'("        so that the asymptotic density of small aggregates is the")')
     write(*,'("        monomer material density. To force another value for the")')
     write(*,'("        prefactor, it can be given explicitly as the third value of the")')
     write(*,'("         mmf  option. The following table summarizes the relevant")')
     write(*,'("        equations.")')
     write(*,'("")')
     write(*,'("                   |  -mmf A0 DF           |  -mmf A0 FILL               ")')
     write(*,'("      -------------+-----------------------+-------------- --------------")')
     write(*,'("       $f$         | $N^(D_\rm f  -3)/3  $ |  given by use 3/D_\rm f    N^")')
     write(*,'("       $D_\rm f  $ |  given by user        | $3\ln N\,/\,\               ")')
     write(*,'("       $k_\rm f  $ | $(5/3)^D_\rm f  /2  $ | $(5/3)^D_\r               ")')
     write(*,'("")')
     write(*,'("        With the structure defined,  optool  then applies the formalism")')
     write(*,'("        from Tazaki & Tanaka (2018) and Tazaki (2021) to compute cross")')
     write(*,'("        sections and the scattering matrix.   optool  also computes the")')
     write(*,'("        phase shift $\Delta\phi$ to check the validity of the scattering")')
     write(*,'("        matrix.  If the condition $\Delta\phi<1$ for accurate scattering")')
     write(*,'("        matrix results is violated, a warning will be issued. However,")')
     write(*,'("        the opacities will remain applicable.")')
     write(*,'("")')
     write(*,'("  CDE")')
     write(*,'("        CDE (Continuous Distribution of Ellipsoids) is an analytical")')
     write(*,'("        formalism by Bohren & Huffman (1998) to compute the opacity of a")')
     write(*,'("        very broad shape distribution.  This method is only applicable")')
     write(*,'("        in the Rayleigh limit $x=2\pi a\ll\lambda$ and")')
     write(*,'("        $|mx|\ll1$.  optool  will issue a warning if the computation")')
     write(*,'("        leaves the bounds of this condition. The scattering matrix will")')
     write(*,'("        be computed from a single sphere in the Rayleigh limit.")')
     write(*,'("")')
     write(*,'("13 Troubleshooting")')
     write(*,'("==================")')
     write(*,'("")')
     write(*,'("  - If you get oscillations in the opacities, in particular at long")')
     write(*,'("    wavelengths, the grain size resolution is not sufficient.  Use more")')
     write(*,'("    grain sizes (*-a*, *-na* and *-d* switches).")')
     write(*,'("  - If you do not remember how to reproduce a specific run, just check")')
     write(*,'("    the output file header. It contains the exact command that was used")')
     write(*,'("    to produce the file.")')
     write(*,'("")')
     write(*,'("14 Acknowledgments")')
     write(*,'("==================")')
     write(*,'("")')
     write(*,'("  We are indebted to")')
     write(*,'("  - the [Jena Database of Optical Constants] and the [Aerosol Refractive")')
     write(*,'("    Index Archive] for their invaluable collections of refractive index")')
     write(*,'("    datasets.")')
     write(*,'("  - Rens Waters, Thomas Henning, Xander Tielens, Elisabetta Palumbo,")')
     write(*,'("    Laurent Pilon, Jeroen Bouwman, and Melissa McClure for discussions")')
     write(*,'("    around optical properties of cosmic dust analogues.")')
     write(*,'("  - Charlène Lefèvre for [SIGMA], which inspired me to add grain")')
     write(*,'("    mantles.")')
     write(*,'("  - Kees Dullemond for discussions about the [RADMC-3D] input format and")')
     write(*,'("    the scattering matrix, for the idea to write  optool2tex  and for")')
     write(*,'("    letting me include his incredible python plotting routine  viewarr ")')
     write(*,'("    ([available on github]).")')
     write(*,'("  - Gabriel-Dominique Marleau for testing and feedback, in particular on")')
     write(*,'("     optool2tex .")')
     write(*,'("")')
     write(*,'("15 Bibliography")')
     write(*,'("===============")')
     write(*,'("")')
     write(*,'("  - Bohren, C.F. and Huffman, D.R. 1998, Wiley-VCH,")')
     write(*,'("    /Absorption and Scattering of Light by Small Particles/")')
     write(*,'("  - Draine, B. 2003, ApJ 598, 1017")')
     write(*,'("  - Draine, B. 2003, ApJ 598, 1026")')
     write(*,'("  - Dorschner, J. et al. 1995, A&A 300, 503")')
     write(*,'("  - Fabian, D. et al. 2001, A&A 378, 228")')
     write(*,'("  - Gerakines, P. and Hudson, R. 2020, ApJ 901, 52")')
     write(*,'("  - Henning, Th. and Stognienko, R. 1996, A&A 311,291")')
     write(*,'("  - Hovenier, J., 2004, [Report available on ADS].")')
     write(*,'("  - Jäger, C. et al. 1998, A&A 339, 904")')
     write(*,'("  - Kitamura, R. et al. 2007, Applied Optics 46,33, p. 8188")')
     write(*,'("  - Koike, C. et al. 1995, Icarus 114, 203")')
     write(*,'("  - Laor, A. and Draine, B. 1993, ApJ 402, 441")')
     write(*,'("  - Martonchik, J. 1984, Applied Optics 23, 541")')
     write(*,'("  - Min, M. et al. 2005, A&A, 432, 909")')
     write(*,'("  - Min, M. et al. 2016, A&A, 585, 13")')
     write(*,'("  - Mishchenko, M. et al. 2002, Cambridge University Press,")')
     write(*,'("    /Scattering, absorption, and emission of light by small particles/")')
     write(*,'("  - Mutschke, H. et al. 2004, A&A 423, 983")')
     write(*,'("  - Okuzumi, S. et al. 2009, ApJ 707, 1247")')
     write(*,'("  - Tazaki, R. et al. 2016, ApJ 823, 70")')
     write(*,'("  - Tazaki, R. & Tanaka, H. 2018, ApJ 860,79")')
     write(*,'("  - Tazaki, R. 2021, MNRAS, in press")')
     write(*,'("  - Toon, O. & Ackerman,T. 1981, Applied Optics 20, 3657")')
     write(*,'("  - Woitke, P. et al. 2016, A&A 586, 103")')
     write(*,'("  - Palumbo, E. et al. 2006, PCCP 8, 279")')
     write(*,'("  - Preibisch, Th. et al. 1993, A&A 279, 577")')
     write(*,'("  - de Rooij W. and van der Stap, C. 1984, A&A 131, 237")')
     write(*,'("  - Steyer, T. 1974, PhD Thesis, The University of Arizona")')
     write(*,'("  - Warren, S. and Brandt, R. 2008, JGRD,113, D14220")')
     write(*,'("  - Warren, S. 1986, Applied Optics 25, 2650")')
     write(*,'("  - Zubko, V. et al. 1996, MNRAS 282, 1321")')
     write(*,'("")')
  endif
end subroutine manual
